local args = {...}

local function refuel()
    for n = 1, 16 do
        if turtle.getItemCount(n) > 0 then
            turtle.select(n)
            if turtle.refuel(0) then
                turtle.refuel(turtle.getItemCount(n))
            end
        end
    end
end

local function tryPlace()
    for n = 1, 16 do
        if turtle.getItemCount(n) > 0 then
            turtle.select(n)
            if turtle.placeDown() then
                return true
            end
        end
    end
    return false
end

local function infiniteForward()
    while true do
        if turtle.getFuelLevel() <= 0 then
            refuel()
        end

        if turtle.getFuelLevel() <= 0 then
            break
        end

        if turtle.detectUp() then
            if not turtle.digUp() then
                break
            end
        end

        if not turtle.detectDown() then
            if not tryPlace() then
                break
            end
        end

        if turtle.detect() then
            if not turtle.dig() then
                break
            end
        end

        if not turtle.forward() then
            break
        end
    end

    if not turtle.detectDown() then
        turtle.back()
    end
end

local function moveForward(d)
    local p = 0
    while true do
        if p == d then
            return true
        end

        if turtle.getFuelLevel() <= 0 then
            refuel()
        end

        if turtle.getFuelLevel() <= 0 then
            break
        end

        if turtle.detectUp() then
            if not turtle.digUp() then
                break
            end
        end

        if not turtle.detectDown() then
            if not tryPlace() then
                break
            end
        end

        if turtle.detect() then
            if not turtle.dig() then
                break
            end
        end

        if not turtle.forward() then
            break
        end

        p = p + 1
    end

    if not turtle.detectDown() then
        turtle.back()
    end

    return false
end

local function xor(a, b)
    return (a or b) and not (a and b)
end

local function moveRelative(forward, left)
    if forward ~= 0 then
        local f = forward
        if forward < 0 then
            turtle.turnLeft()
            turtle.turnLeft()
            f = -f
        end
        if not moveForward(f) then
            return false
        end
    end

    if left ~= 0 then
        local l = left
        if left < 0 then
            l = -l
        end

        if xor(left < 0, forward < 0) then
            turtle.turnLeft()
        else
            turtle.turnRight()
        end

        if not moveForward(l) then
            return false
        end
    end

    return true
end

local function turnToPx(dx, dz)
    if dx < 0 then
        turtle.turnLeft()
        turtle.turnLeft()
    elseif dz < 0 then
        turtle.turnRight()
    elseif dz > 0 then
        turtle.turnLeft()
    end
end

local function findDelta(cx, cz)
    local turnOut = 4
    while not turtle.forward() and turnOut > 0 do
        turtle.turnLeft()
        turnOut = turnOut - 1
    end

    if turnOut <= 0 then
        turnOut = 4
        while not turtle.dig() and turnOut > 0 do
            turtle.turnLeft()
            turnOut = turnOut - 1
        end

        if turnOut <= 0 then
            return
        else
            turtle.forward()
        end
    end

    local fx, fy, fz = gps.locate()

    turtle.back()

    return fx - cx, fz - cz
end

local function moveAbsolute(x, z)
    local cx, cy, cz = gps.locate(2, true)
    if not cx then
        return false
    end

    local dx, dz = findDelta(cx, cz)
    if not dx then
        return false
    end

    turnToPx(dx, dz)

    moveRelative(x - cx, z - cz)
end

if #args == 0 then
    infiniteForward()
elseif #args == 1 then
    if args[1] == "-Rs" then
        local cx, cy, cz = gps.locate(2, true)
        if cx then
            toPx(cx, cz)
        end
    else
        local amount = tonumber(args[1])
        if amount < 0 then
            turtle.turnLeft()
            turtle.turnLeft()
            amount = -amount
        end
        moveForward(amount)
    end
elseif #args == 2 then
    moveRelative(tonumber(args[1]), tonumber(args[2]))
elseif #args == 3 then
    if args[1] == "-r" then
        moveRelative(tonumber(args[2]), tonumber(args[3]))
    elseif args[1] == "-g" then
        moveAbsolute(tonumber(args[2]), tonumber(args[3]))
    end
elseif #args == 5 then
    if args[1] == "-g" then
        local cx, cy, cz = gps.locate(2, true)
        if cx then
            turnToPx(tonumber(args[4]), tonumber(args[5]))
            moveRelative(tonumber(args[2]) - cx, tonumber(args[3]) - cz)
        end
    end
end

if not turtle.detectDown() then
    turtle.back()
end
